#ifndef _PS_FRAME_DEMUXER_H
#define _PS_FRAME_DEMUXER_H

// --------------------------------------------------------------------

typedef struct _str_PsPackHeader
{
    char start_code[4];             // == 0x000001BA
    char scr[6];
    char program_mux_rate[3];       // == 0x000003
    char pack_stuffing_length;      // == 0xF8
} PsPackHeader;

typedef struct _str_PsSystemHeader
{
    char start_code[4];             // == 0x000001BB
    char header_length[2];          // == 6 + 3 * stream_count(2)
    char rate_bound[3];             // == 0x800001
    char CSPS_flag : 1;             // == 0
    char fixed_flag : 1;            // == 0
    char audio_bound : 6;           // audio stream number
    char video_bound : 5;           // video stream number
    char marker_bit : 1;            // == 1
    char system_video_lock_flag : 1;// == 1
    char system_audio_lock_flag : 1;// == 1
    char reserved_byte;             // == 0xFF
} PsSystemHeader;

typedef struct _str_PsSystemMap
{
    char start_code[4];             // == 0x000001BC
    char header_length[2];          // == 6 + es_map_length
    char ps_map_version : 5;        // == 0
    char reserved1 : 2;             // == 3
    char current_next_indicator : 1;// == 1
    char marker_bit : 1;            // == 1
    char reserved2 : 7;             // == 127
    char ps_info_length[2];         // == 0
    char es_map_length[2];          // == 4 * es_num
} PsSystemMap;

typedef struct _str_PsSystemMapEs
{
    char stream_type;
    char es_id;
    char es_info_length[2];
} PsSystemMapEs;

#define MAX_STREAM_NUM      (4)     // 每个节目的详情

#define MAX_PROGRAM_NUM     (1)     // 节目信息（目前最多支持1个节目2条流）


// 每条流的详情

typedef struct _str_PsStreamSpec
{
    unsigned char stream_type;      // [I]媒体类型

    unsigned char stream_id;        // [O]实体流ID（与PES头部id相同）

    int es_pid;                     // [O]实体流的PID

} PsStreamSpec;

typedef struct _str_PsProgramSpec
{
    int stream_num;                 // [I]这个节目包含的流个数

    int key_stream_id;              // {I]基准流编号

    int pmt_pid;                    // [O]这个节目对应的PMT表的PID（TS解码用）

    int mux_rate;                   // [O]这个节目的码率，单位为50字节每秒(PS编码用)

    PsStreamSpec stream[MAX_STREAM_NUM];
} PsProgramSpec;

typedef struct _str_PsProgramInfo
{
    int program_num;                // [I]对于PS为1

    int pat_pmt_counter;            // [O]PAT、PMT计数器

    PsProgramSpec prog[MAX_PROGRAM_NUM];
} PsProgramInfo;

typedef struct _str_PsContext
{
    PsProgramInfo info;      // 节目信息

    int is_pes;              // 属于数据，不是PSI

    int pid;                 // 当前包的PID

    int program_no;          // 当前包所属的节目号

    int stream_no;           // 当前包所属的流号

    unsigned long long pts;  // 当前包的时间戳


    unsigned char *pack_ptr; // 解出一包的首地址

    int pack_len;            // 解出一包的长度

    unsigned char *es_ptr;   // ES数据首地址

    int es_len;              // ES数据长度

    int pes_head_len;        // PES头部长度

    int ps_started;          // 已找到PS头部

} PsContext;


// --------------------------------------------------------------------
// RtpNetOptimizationCallback

class PSFrameDemuxerCallback
{
public:
    virtual void OnVideoFrame(const unsigned char * pszBuffer, unsigned bufferSize, int streamType, unsigned timestamp) = 0;
    virtual void OnAudioFrame(const unsigned char * pszBuffer, unsigned bufferSize, int streamType, unsigned timestamp) = 0;
};



class PsFrameDemuxer
{
public:
    PsFrameDemuxer(PSFrameDemuxerCallback * pCallback);
    virtual ~PsFrameDemuxer();

public:
    void GetStatisticCnt(unsigned & uPsPacketCnt, unsigned & uVideoPacketCnt, unsigned & uAudioPacketCnt);
    void GetMediaStreamType(int & iVideoStreamType, int & iAudioStreamType);
    void ResetStatisticParam();

public:
    virtual void OnPsFrame(const unsigned char * pszBuffer, unsigned bufferSize, unsigned long timestamp);

private:
    int ParsePsFrame(const unsigned char * pszBuffer, unsigned bufferSize, unsigned long timestamp);
    int PSFrameDemux(PsContext * context, const unsigned char * pszBuffer, unsigned bufferSize);

private:
    int HandlePsHeader(PsContext * context, unsigned char * buffer, int bufSize);
    int HandlePsSystemHeader(PsContext * context, unsigned char * buffer, int bufSize);
    int HandlePsSystemMap(PsContext * context, unsigned char * buffer, int bufSize);
    int HandlePsFinish(PsContext * context, unsigned char * buffer, int bufSize);

    int HandlePes(PsContext * context, unsigned char * buffer, int bufSize);
    int HandlePesHeader(unsigned char * pesBuffer, int pesBufSize, unsigned char * streamId, unsigned long long * pts, int * esSize);

    int GetPesHeadSize(unsigned char * pesBuffer, int pesBufSize);

    int SizeCheck(unsigned char * buffer, int bufSize);

private:
    PSFrameDemuxerCallback * m_pCallback;
    PsContext m_sPsContext;

    unsigned m_uPsPacketCnt;    
    unsigned m_uVideoPacketCnt;
    unsigned m_uAudioPacketCnt;

    int m_iVideoStreamType;     
    int m_iAudioStreamType;    
};

#endif
